home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
gfx
/
x11
/
twm_930531.lha
/
twm
/
menus.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-30
|
71KB
|
2,961 lines
/*****************************************************************************/
/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
/** Salt Lake City, Utah **/
/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
/** Cambridge, Massachusetts **/
/** **/
/** All Rights Reserved **/
/** **/
/** Permission to use, copy, modify, and distribute this software and **/
/** its documentation for any purpose and without fee is hereby **/
/** granted, provided that the above copyright notice appear in all **/
/** copies and that both that copyright notice and this permis- **/
/** sion notice appear in supporting documentation, and that the **/
/** names of Evans & Sutherland and M.I.T. not be used in advertising **/
/** in publicity pertaining to distribution of the software without **/
/** specific, written prior permission. **/
/** **/
/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
/** OR PERFORMANCE OF THIS SOFTWARE. **/
/*****************************************************************************/
/***********************************************************************
*
* $XConsortium: menus.c,v 1.186 91/07/17 13:58:00 dave Exp $
*
* twm menu code
*
* 17-Nov-87 Thomas E. LaStrange File created
*
***********************************************************************/
#include <stdio.h>
#include <signal.h>
#include <X11/Xos.h>
#include "twm.h"
#include "gc.h"
#include "menus.h"
#include "resize.h"
#include "events.h"
#include "util.h"
#include "parse.h"
#include "gram.h"
#include "screen.h"
#include <X11/Xmu/CharSet.h>
#include <X11/bitmaps/menu12>
#include "version.h"
extern XEvent Event;
int RootFunction = NULL;
MenuRoot *ActiveMenu = NULL; /* the active menu */
MenuItem *ActiveItem = NULL; /* the active menu item */
int MoveFunction; /* either F_MOVE or F_FORCEMOVE */
int WindowMoved = FALSE;
int menuFromFrameOrWindowOrTitlebar = FALSE;
int ConstMove = FALSE; /* constrained move variables */
int ConstMoveDir;
int ConstMoveX;
int ConstMoveY;
int ConstMoveXL;
int ConstMoveXR;
int ConstMoveYT;
int ConstMoveYB;
/* Globals used to keep track of whether the mouse has moved during
a resize function. */
int ResizeOrigX;
int ResizeOrigY;
int MenuDepth = 0; /* number of menus up */
static struct {
int x;
int y;
} MenuOrigins[MAXMENUDEPTH];
static Cursor LastCursor;
void WarpAlongRing(), WarpToWindow();
extern char *Action;
extern int Context;
extern TwmWindow *ButtonWindow, *Tmp_win;
extern XEvent Event, ButtonEvent;
extern char *InitFile;
static void Identify();
#define SHADOWWIDTH 5 /* in pixels */
/***********************************************************************
*
* Procedure:
* InitMenus - initialize menu roots
*
***********************************************************************
*/
void
InitMenus()
{
int i, j, k;
FuncKey *key, *tmp;
for (i = 0; i < MAX_BUTTONS+1; i++)
for (j = 0; j < NUM_CONTEXTS; j++)
for (k = 0; k < MOD_SIZE; k++)
{
Scr->Mouse[i][j][k].func = NULL;
Scr->Mouse[i][j][k].item = NULL;
}
Scr->DefaultFunction.func = NULL;
Scr->WindowFunction.func = NULL;
if (FirstScreen)
{
for (key = Scr->FuncKeyRoot.next; key != NULL;)
{
free(key->name);
tmp = key;
key = key->next;
free((char *) tmp);
}
Scr->FuncKeyRoot.next = NULL;
}
}
/***********************************************************************
*
* Procedure:
* AddFuncKey - add a function key to the list
*
* Inputs:
* name - the name of the key
* cont - the context to look for the key press in
* mods - modifier keys that need to be pressed
* func - the function to perform
* win_name- the window name (if any)
* action - the action string associated with the function (if any)
*
***********************************************************************
*/
Bool AddFuncKey (name, cont, mods, func, win_name, action)
char *name;
int cont, mods, func;
char *win_name;
char *action;
{
FuncKey *tmp;
KeySym keysym;
KeyCode keycode;
/*
* Don't let a 0 keycode go through, since that means AnyKey to the
* XGrabKey call in GrabKeys().
*/
if ((keysym = XStringToKeysym(name)) == NoSymbol ||
(keycode = XKeysymToKeycode(dpy, keysym)) == 0)
{
return False;
}
/* see if there already is a key defined for this context */
for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
{
if (tmp->keysym == keysym &&
tmp->cont == cont &&
tmp->mods == mods)
break;
}
if (tmp == NULL)
{
tmp = (FuncKey *) malloc(sizeof(FuncKey));
tmp->next = Scr->FuncKeyRoot.next;
Scr->FuncKeyRoot.next = tmp;
}
tmp->name = name;
tmp->keysym = keysym;
tmp->keycode = keycode;
tmp->cont = cont;
tmp->mods = mods;
tmp->func = func;
tmp->win_name = win_name;
tmp->action = action;
return True;
}
int CreateTitleButton (name, func, action, menuroot, rightside, append)
char *name;
int func;
char *action;
MenuRoot *menuroot;
Bool rightside;
Bool append;
{
TitleButton *tb = (TitleButton *) malloc (sizeof(TitleButton));
if (!tb) {
fprintf (stderr,
"%s: unable to allocate %d bytes for title button\n",
ProgramName, sizeof(TitleButton));
return 0;
}
tb->next = NULL;
tb->name = name; /* note that we are not copying */
tb->bitmap = None; /* WARNING, values not set yet */
tb->width = 0; /* see InitTitlebarButtons */
tb->height = 0; /* ditto */
tb->func = func;
tb->action = action;
tb->menuroot = menuroot;
tb->rightside = rightside;
if (rightside) {
Scr->TBInfo.nright++;
} else {
Scr->TBInfo.nleft++;
}
/*
* Cases for list:
*
* 1. empty list, prepend left put at head of list
* 2. append left, prepend right put in between left and right
* 3. append right put at tail of list
*
* Do not refer to widths and heights yet since buttons not created
* (since fonts not loaded and heights not known).
*/
if ((!Scr->TBInfo.head) || ((!append) && (!rightside))) { /* 1 */
tb->next = Scr->TBInfo.head;
Scr->TBInfo.head = tb;
} else if (append && rightside) { /* 3 */
register TitleButton *t;
for /* SUPPRESS 530 */
(t = Scr->TBInfo.head; t->next; t = t->next);
t->next = tb;
tb->next = NULL;
} else { /* 2 */
register TitleButton *t, *prev = NULL;
for (t = Scr->TBInfo.head; t && !t->rightside; t = t->next) {
prev = t;
}
if (prev) {
tb->next = prev->next;
prev->next = tb;
} else {
tb->next = Scr->TBInfo.head;
Scr->TBInfo.head = tb;
}
}
return 1;
}
/*
* InitTitlebarButtons - Do all the necessary stuff to load in a titlebar
* button. If we can't find the button, then put in a question; if we can't
* find the question mark, something is wrong and we are probably going to be
* in trouble later on.
*/
void InitTitlebarButtons ()
{
TitleButton *tb;
int h;
/*
* initialize dimensions
*/
Scr->TBInfo.width = (Scr->TitleHeight -
2 * (Scr->FramePadding + Scr->ButtonIndent));
Scr->TBInfo.pad = ((Scr->TitlePadding > 1)
? ((Scr->TitlePadding + 1) / 2) : 1);
h = Scr->TBInfo.width - 2 * Scr->TBInfo.border;
/*
* add in some useful buttons and bindings so that novices can still
* use the system.
*/
if (!Scr->NoDefaults) {
/* insert extra buttons */
if (!CreateTitleButton (TBPM_ICONIFY, F_ICONIFY, "", (MenuRoot *) NULL,
False, False)) {
fprintf (stderr, "%s: unable to add iconify button\n",
ProgramName);
}
if (!CreateTitleButton (TBPM_RESIZE, F_RESIZE, "", (MenuRoot *) NULL,
True, True)) {
fprintf (stderr, "%s: unable to add resize button\n",
ProgramName);
}
AddDefaultBindings ();
}
ComputeCommonTitleOffsets ();
/*
* load in images and do appropriate centering
*/
for (tb = Scr->TBInfo.head; tb; tb = tb->next) {
tb->bitmap = FindBitmap (tb->name, &tb->width, &tb->height);
if (!tb->bitmap) {
tb->bitmap = FindBitmap (TBPM_QUESTION, &tb->width, &tb->height);
if (!tb->bitmap) { /* cannot happen (see util.c) */
fprintf (stderr,
"%s: unable to add titlebar button \"%s\"\n",
ProgramName, tb->name);
}
}
tb->dstx = (h - tb->width + 1) / 2;
if (tb->dstx < 0) { /* clip to minimize copying */
tb->srcx = -(tb->dstx);
tb->width = h;
tb->dstx = 0;
} else {
tb->srcx = 0;
}
tb->dsty = (h - tb->height + 1) / 2;
if (tb->dsty < 0) {
tb->srcy = -(tb->dsty);
tb->height = h;
tb->dsty = 0;
} else {
tb->srcy = 0;
}
}
}
PaintEntry(mr, mi, exposure)
MenuRoot *mr;
MenuItem *mi;
int exposure;
{
int y_offset;
int text_y;
GC gc;
#ifdef DEBUG_MENUS
fprintf(stderr, "Paint entry\n");
#endif
y_offset = mi->item_num * Scr->EntryHeight;
text_y = y_offset + Scr->MenuFont.y;
if (mi->func != F_TITLE)
{
int x, y;
if (mi->state)
{
XSetForeground(dpy, Scr->NormalGC, mi->hi_back);
XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, Scr->EntryHeight);
FBF(mi->hi_fore, mi->hi_back, Scr->MenuFont.font->fid);
XDrawString(dpy, mr->w, Scr->NormalGC, mi->x,
text_y, mi->item, mi->strlen);
gc = Scr->NormalGC;
}
else
{
if (mi->user_colors || !exposure)
{
XSetForeground(dpy, Scr->NormalGC, mi->back);
XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, Scr->EntryHeight);
FBF(mi->fore, mi->back, Scr->MenuFont.font->fid);
gc = Scr->NormalGC;
}
else
gc = Scr->MenuGC;
XDrawString(dpy, mr->w, gc, mi->x,
text_y, mi->item, mi->strlen);
}
if (mi->func == F_MENU)
{
/* create the pull right pixmap if needed */
if (Scr->pullPm == None)
{
Scr->pullPm = CreateMenuIcon (Scr->MenuFont.height,
&Scr->pullW, &Scr->pullH);
}
x = mr->width - Scr->pullW - 5;
y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2);
XCopyPlane(dpy, Scr->pullPm, mr->w, gc, 0, 0,
Scr->pullW, Scr->pullH, x, y, 1);
}
}
else
{
int y;
XSetForeground(dpy, Scr->NormalGC, mi->back);
/* fill the rectangle with the title background color */
XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, Scr->EntryHeight);
{
XSetForeground(dpy, Scr->NormalGC, mi->fore);
/* now draw the dividing lines */
if (y_offset)
XDrawLine (dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, y_offset);
y = ((mi->item_num+1) * Scr->EntryHeight)-1;
XDrawLine(dpy, mr->w, Scr->NormalGC, 0, y, mr->width, y);
}
FBF(mi->fore, mi->back, Scr->MenuFont.font->fid);
/* finally render the title */
XDrawString(dpy, mr->w, Scr->NormalGC, mi->x,
text_y, mi->item, mi->strlen);
}
}
PaintMenu(mr, e)
MenuRoot *mr;
XEvent *e;
{
MenuItem *mi;
for (mi = mr->first; mi != NULL; mi = mi->next)
{
int y_offset = mi->item_num * Scr->EntryHeight;
/* be smart about handling the expose, redraw only the entries
* that we need to
*/
if (e->xexpose.y < (y_offset + Scr->EntryHeight) &&
(e->xexpose.y + e->xexpose.height) > y_offset)
{
PaintEntry(mr, mi, True);
}
}
XSync(dpy, 0);
}
static Bool fromMenu;
UpdateMenu()
{
MenuItem *mi;
int i, x, y, x_root, y_root, entry;
int done;
MenuItem *badItem = NULL;
fromMenu = TRUE;
while (TRUE)
{
/* block until there is an event */
if (!menuFromFrameOrWindowOrTitlebar) {
XMaskEvent(dpy,
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | ExposureMask |
VisibilityChangeMask | LeaveWindowMask |
ButtonMotionMask, &Event);
}
if (Event.type == MotionNotify) {
/* discard any extra motion events before a release */
while(XCheckMaskEvent(dpy,
ButtonMotionMask | ButtonReleaseMask, &Event))
if (Event.type == ButtonRelease)
break;
}
if (!DispatchEvent ())
continue;
if (Event.type == ButtonRelease || Cancel) {
menuFromFrameOrWindowOrTitlebar = FALSE;
fromMenu = FALSE;
return;
}
if (Event.type != MotionNotify)
continue;
done = FALSE;
XQueryPointer( dpy, ActiveMenu->w, &JunkRoot, &JunkChild,
&x_root, &y_root, &x, &y, &JunkMask);
/* if we haven't recieved the enter notify yet, wait */
if (ActiveMenu && !ActiveMenu->entered)
continue;
XFindContext(dpy, ActiveMenu->w, ScreenContext, (caddr_t *)&Scr);
if (x < 0 || y < 0 ||
x >= ActiveMenu->width || y >= ActiveMenu->height)
{
if (ActiveItem && ActiveItem->func != F_TITLE)
{
ActiveItem->state = 0;
PaintEntry(ActiveMenu, ActiveItem, False);
}
ActiveItem = NULL;
continue;
}
/* look for the entry that the mouse is in */
entry = y / Scr->EntryHeight;
for (i = 0, mi = ActiveMenu->first; mi != NULL; i++, mi=mi->next)
{
if (i == entry)
break;
}
/* if there is an active item, we might have to turn it off */
if (ActiveItem)
{
/* is the active item the one we are on ? */
if (ActiveItem->item_num == entry && ActiveItem->state)
done = TRUE;
/* if we weren't on the active entry, let's turn the old
* active one off
*/
if (!done && ActiveItem->func != F_TITLE)
{
ActiveItem->state = 0;
PaintEntry(ActiveMenu, ActiveItem, False);
}
}
/* if we weren't on the active item, change the active item and turn
* it on
*/
if (!done)
{
ActiveItem = mi;
if (ActiveItem->func != F_TITLE && !ActiveItem->state)
{
ActiveItem->state = 1;
PaintEntry(ActiveMenu, ActiveItem, False);
}
}
/* now check to see if we were over the arrow of a pull right entry */
if (ActiveItem->func == F_MENU &&
((ActiveMenu->width - x) < (ActiveMenu->width >> 1)))
{
MenuRoot *save = ActiveMenu;
int savex = MenuOrigins[MenuDepth - 1].x;
int savey = MenuOrigins[MenuDepth - 1].y;
if (MenuDepth < MAXMENUDEPTH) {
PopUpMenu (ActiveItem->sub,
(savex + (ActiveMenu->width >> 1)),
(savey + ActiveItem->item_num * Scr->EntryHeight)
/*(savey + ActiveItem->item_num * Scr->EntryHeight +
(Scr->EntryHeight >> 1))*/, False);
} else if (!badItem) {
XBell (dpy, 0);
badItem = ActiveItem;
}
/* if the menu did get popped up, unhighlight the active item */
if (save != ActiveMenu && ActiveItem->state)
{
ActiveItem->state = 0;
PaintEntry(save, ActiveItem, False);
ActiveItem = NULL;
}
}
if (badItem != ActiveItem) badItem = NULL;
XFlush(dpy);
}
}
/***********************************************************************
*
* Procedure:
* NewMenuRoot - create a new menu root
*
* Returned Value:
* (MenuRoot *)
*
* Inputs:
* name - the name of the menu root
*
***********************************************************************
*/
MenuRoot *
NewMenuRoot(name)
char *name;
{
MenuRoot *tmp;
#define UNUSED_PIXEL ((unsigned long) (~0)) /* more than 24 bits */
tmp = (MenuRoot *) malloc(sizeof(MenuRoot));
tmp->hi_fore = UNUSED_PIXEL;
tmp->hi_back = UNUSED_PIXEL;
tmp->name = name;
tmp->prev = NULL;
tmp->first = NULL;
tmp->last = NULL;
tmp->items = 0;
tmp->width = 0;
tmp->mapped = NEVER_MAPPED;
tmp->pull = FALSE;
tmp->w = None;
tmp->shadow = None;
tmp->real_menu = FALSE;
if (Scr->MenuList == NULL)
{
Scr->MenuList = tmp;
Scr->MenuList->next = NULL;
}
if (Scr->LastMenu == NULL)
{
Scr->LastMenu = tmp;
Scr->LastMenu->next = NULL;
}
else
{
Scr->LastMenu->next = tmp;
Scr->LastMenu = tmp;
Scr->LastMenu->next = NULL;
}
if (strcmp(name, TWM_WINDOWS) == 0)
Scr->Windows = tmp;
return (tmp);
}
/***********************************************************************
*
* Procedure:
* AddToMenu - add an item to a root menu
*
* Returned Value:
* (MenuItem *)
*
* Inputs:
* menu - pointer to the root menu to add the item
* item - the text to appear in the menu
* action - the string to possibly execute
* sub - the menu root if it is a pull-right entry
* func - the numeric function
* fore - foreground color string
* back - background color string
*
***********************************************************************
*/
MenuItem *
AddToMenu(menu, item, action, sub, func, fore, back)
MenuRoot *menu;
char *item, *action;
MenuRoot *sub;
int func;
char *fore, *back;
{
MenuItem *tmp;
int width;
#ifdef DEBUG_MENUS
fprintf(stderr, "adding menu item=\"%s\", action=%s, sub=%d, f=%d\n",
item, action, sub, func);
#endif
tmp = (MenuItem *) malloc(sizeof(MenuItem));
tmp->root = menu;
if (menu->first == NULL)
{
menu->first = tmp;
tmp->prev = NULL;
}
else
{
menu->last->next = tmp;
tmp->prev = menu->last;
}
menu->last = tmp;
tmp->item = item;
tmp->strlen = strlen(item);
tmp->action = action;
tmp->next = NULL;
tmp->sub = NULL;
tmp->state = 0;
tmp->func = func;
if (!Scr->HaveFonts) CreateFonts();
width = XTextWidth(Scr->MenuFont.font, item, tmp->strlen);
if (width <= 0)
width = 1;
if (width > menu->width)
menu->width = width;
tmp->user_colors = FALSE;
if (Scr->Monochrome == COLOR && fore != NULL)
{
int save;
save = Scr->FirstTime;
Scr->FirstTime = TRUE;
GetColor(COLOR, &tmp->fore, fore);
GetColor(COLOR, &tmp->back, back);
Scr->FirstTime = save;
tmp->user_colors = TRUE;
}
if (sub != NULL)
{
tmp->sub = sub;
menu->pull = TRUE;
}
tmp->item_num = menu->items++;
return (tmp);
}
MakeMenus()
{
MenuRoot *mr;
for (mr = Scr->MenuList; mr != NULL; mr = mr->next)
{
if (mr->real_menu == FALSE)
continue;
MakeMenu(mr);
}
}
MakeMenu(mr)
MenuRoot *mr;
{
MenuItem *start, *end, *cur, *tmp;
XColor f1, f2, f3;
XColor b1, b2, b3;
XColor save_fore, save_back;
int num, i;
int fred, fgreen, fblue;
int bred, bgreen, bblue;
int width;
unsigned long valuemask;
XSetWindowAttributes attributes;
Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
Scr->EntryHeight = Scr->MenuFont.height + 4;
/* lets first size the window accordingly */
if (mr->mapped == NEVER_MAPPED)
{
if (mr->pull == TRUE)
{
mr->width += 16 + 10;
}
width = mr->width + 10;
for (cur = mr->first; cur != NULL; cur = cur->next)
{
if (cur->func != F_TITLE)
cur->x = 5;
else
{
cur->x = width - XTextWidth(Scr->MenuFont.font, cur->item,
cur->strlen);
cur->x /= 2;
}
}
mr->height = mr->items * Scr->EntryHeight;
mr->width += 10;
if (Scr->Shadow)
{
/*
* Make sure that you don't draw into the shadow window or else
* the background bits there will get saved
*/
valuemask = (CWBackPixel | CWBorderPixel);
attributes.background_pixel = Scr->MenuShadowColor;
attributes.border_pixel = Scr->MenuShadowColor;
if (Scr->SaveUnder) {
valuemask |= CWSaveUnder;
attributes.save_under = True;
}
mr->shadow = XCreateWindow (dpy, Scr->Root, 0, 0,
(unsigned int) mr->width,
(unsigned int) mr->height,
(unsigned int)0,
CopyFromParent,
(unsigned int) CopyFromParent,
(Visual *) CopyFromParent,
valuemask, &attributes);
}
valuemask = (CWBackPixel | CWBorderPixel | CWEventMask);
attributes.background_pixel = Scr->MenuC.back;
attributes.border_pixel = Scr->MenuC.fore;
attributes.event_mask = (ExposureMask | EnterWindowMask);
if (Scr->SaveUnder) {
valuemask |= CWSaveUnder;
attributes.save_under = True;
}
if (Scr->BackingStore) {
valuemask |= CWBackingStore;
attributes.backing_store = Always;
}
mr->w = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) mr->width,
(unsigned int) mr->height, (unsigned int) 1,
CopyFromParent, (unsigned int) CopyFromParent,
(Visual *) CopyFromParent,
valuemask, &attributes);
XSaveContext(dpy, mr->w, MenuContext, (caddr_t)mr);
XSaveContext(dpy, mr->w, ScreenContext, (caddr_t)Scr);
mr->mapped = UNMAPPED;
}
/* get the default colors into the menus */
for (tmp = mr->first; tmp != NULL; tmp = tmp->next)
{
if (!tmp->user_colors) {
if (tmp->func != F_TITLE) {
tmp->fore = Scr->MenuC.fore;
tmp->back = Scr->MenuC.back;
} else {
tmp->fore = Scr->MenuTitleC.fore;
tmp->back = Scr->MenuTitleC.back;
}
}
if (mr->hi_fore != UNUSED_PIXEL)
{
tmp->hi_fore = mr->hi_fore;
tmp->hi_back = mr->hi_back;
}
else
{
tmp->hi_fore = tmp->back;
tmp->hi_back = tmp->fore;
}
}
if (Scr->Monochrome == MONOCHROME || !Scr->InterpolateMenuColors)
return;
start = mr->first;
while (TRUE)
{
for (; start != NULL; start = start->next)
{
if (start->user_colors)
break;
}
if (start == NULL)
break;
for (end = start->next; end != NULL; end = end->next)
{
if (end->user_colors)
break;
}
if (end == NULL)
break;
/* we have a start and end to interpolate between */
num = end->item_num - start->item_num;
f1.pixel = start->fore;
XQueryColor(dpy, cmap, &f1);
f2.pixel = end->fore;
XQueryColor(dpy, cmap, &f2);
b1.pixel = start->back;
XQueryColor(dpy, cmap, &b1);
b2.pixel = end->back;
XQueryColor(dpy, cmap, &b2);
fred = ((int)f2.red - (int)f1.red) / num;
fgreen = ((int)f2.green - (int)f1.green) / num;
fblue = ((int)f2.blue - (int)f1.blue) / num;
bred = ((int)b2.red - (int)b1.red) / num;
bgreen = ((int)b2.green - (int)b1.green) / num;
bblue = ((int)b2.blue - (int)b1.blue) / num;
f3 = f1;
f3.flags = DoRed | DoGreen | DoBlue;
b3 = b1;
b3.flags = DoRed | DoGreen | DoBlue;
num -= 1;
for (i = 0, cur = start->next; i < num; i++, cur = cur->next)
{
f3.red += fred;
f3.green += fgreen;
f3.blue += fblue;
save_fore = f3;
b3.red += bred;
b3.green += bgreen;
b3.blue += bblue;
save_back = b3;
XAllocColor(dpy, cmap, &f3);
XAllocColor(dpy, cmap, &b3);
cur->hi_back = cur->fore = f3.pixel;
cur->hi_fore = cur->back = b3.pixel;
cur->user_colors = True;
f3 = save_fore;
b3 = save_back;
}
start = end;
}
}
/***********************************************************************
*
* Procedure:
* PopUpMenu - pop up a pull down menu
*
* Inputs:
* menu - the root pointer of the menu to pop up
* x, y - location of upper left of menu
* center - whether or not to center horizontally over position
*
***********************************************************************
*/
Bool PopUpMenu (menu, x, y, center)
MenuRoot *menu;
int x, y;
Bool center;
{
int WindowNameOffset, WindowNameCount;
TwmWindow **WindowNames;
TwmWindow *tmp_win2,*tmp_win3;
int i;
int (*compar)() =
(Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1);
if (!menu) return False;
InstallRootColormap();
if (menu == Scr->Windows)
{
TwmWindow *tmp_win;
/* this is the twm windows menu, let's go ahead and build it */
DestroyMenu (menu);
menu->first = NULL;
menu->last = NULL;
menu->items = 0;
menu->width = 0;
menu->mapped = NEVER_MAPPED;
AddToMenu(menu, "TWM Windows", NULLSTR, NULL, F_TITLE,NULLSTR,NULLSTR);
WindowNameOffset=(char *)Scr->TwmRoot.next->name -
(char *)Scr->TwmRoot.next;
for(tmp_win = Scr->TwmRoot.next , WindowNameCount=0;
tmp_win != NULL;
tmp_win = tmp_win->next)
WindowNameCount++;
WindowNames =
(TwmWindow **)malloc(sizeof(TwmWindow *)*WindowNameCount);
WindowNames[0] = Scr->TwmRoot.next;
for(tmp_win = Scr->TwmRoot.next->next , WindowNameCount=1;
tmp_win != NULL;
tmp_win = tmp_win->next,WindowNameCount++)
{
tmp_win2 = tmp_win;
for (i=0;i<WindowNameCount;i++)
{
if ((*compar)(tmp_win2->name,WindowNames[i]->name) < 0)
{
tmp_win3 = tmp_win2;
tmp_win2 = WindowNames[i];
WindowNames[i] = tmp_win3;
}
}
WindowNames[WindowNameCount] = tmp_win2;
}
for (i=0; i<WindowNameCount; i++)
{
AddToMenu(menu, WindowNames[i]->name, (char *)WindowNames[i],
NULL, F_POPUP,NULL,NULL);
}
free(WindowNames);
MakeMenu(menu);
}
if (menu->w == None || menu->items == 0) return False;
/* Prevent recursively bringing up menus. */
if (menu->mapped == MAPPED) return False;
/*
* Dynamically set the parent; this allows pull-ups to also be main
* menus, or to be brought up from more than one place.
*/
menu->prev = ActiveMenu;
XGrabPointer(dpy, Scr->Root, True,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | PointerMotionHintMask,
GrabModeAsync, GrabModeAsync,
Scr->Root, Scr->MenuCursor, CurrentTime);
ActiveMenu = menu;
menu->mapped = MAPPED;
menu->entered = FALSE;
if (center) {
x -= (menu->width / 2);
y -= (Scr->EntryHeight / 2); /* sticky menus would be nice here */
}
/*
* clip to screen
*/
if (x + menu->width > Scr->MyDisplayWidth) {
x = Scr->MyDisplayWidth - menu->width;
}
if (x < 0) x = 0;
if (y + menu->height > Scr->MyDisplayHeight) {
y = Scr->MyDisplayHeight - menu->height;
}
if (y < 0) y = 0;
MenuOrigins[MenuDepth].x = x;
MenuOrigins[MenuDepth].y = y;
MenuDepth++;
XMoveWindow(dpy, menu->w, x, y);
if (Scr->Shadow) {
XMoveWindow (dpy, menu->shadow, x + SHADOWWIDTH, y + SHADOWWIDTH);
}
if (Scr->Shadow) {
XRaiseWindow (dpy, menu->shadow);
}
XMapRaised(dpy, menu->w);
if (Scr->Shadow) {
XMapWindow (dpy, menu->shadow);
}
XSync(dpy, 0);
return True;
}
/***********************************************************************
*
* Procedure:
* PopDownMenu - unhighlight the current menu selection and
* take down the menus
*
***********************************************************************
*/
PopDownMenu()
{
MenuRoot *tmp;
if (ActiveMenu == NULL)
return;
if (ActiveItem)
{
ActiveItem->state = 0;
PaintEntry(ActiveMenu, ActiveItem, False);
}
for (tmp = ActiveMenu; tmp != NULL; tmp = tmp->prev)
{
if (Scr->Shadow) {
XUnmapWindow (dpy, tmp->shadow);
}
XUnmapWindow(dpy, tmp->w);
tmp->mapped = UNMAPPED;
UninstallRootColormap();
}
XFlush(dpy);
ActiveMenu = NULL;
ActiveItem = NULL;
MenuDepth = 0;
if (Context == C_WINDOW || Context == C_FRAME || Context == C_TITLE)
menuFromFrameOrWindowOrTitlebar = TRUE;
}
/***********************************************************************
*
* Procedure:
* FindMenuRoot - look for a menu root
*
* Returned Value:
* (MenuRoot *) - a pointer to the menu root structure
*
* Inputs:
* name - the name of the menu root
*
***********************************************************************
*/
MenuRoot *
FindMenuRoot(name)
char *name;
{
MenuRoot *tmp;
for (tmp = Scr->MenuList; tmp != NULL; tmp = tmp->next)
{
if (strcmp(name, tmp->name) == 0)
return (tmp);
}
return NULL;
}
static Bool belongs_to_twm_window (t, w)
register TwmWindow *t;
register Window w;
{
if (!t) return False;
if (w == t->frame || w == t->title_w || w == t->hilite_w ||
w == t->icon_w || w == t->icon_bm_w) return True;
if (t && t->titlebuttons) {
register TBWindow *tbw;
register int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
for (tbw = t->titlebuttons; nb > 0; tbw++, nb--) {
if (tbw->window == w) return True;
}
}
return False;
}
/***********************************************************************
*
* Procedure:
* resizeFromCenter -
*
***********************************************************************
*/
extern int AddingX;
extern int AddingY;
extern int AddingW;
extern int AddingH;
void resizeFromCenter(w, tmp_win)
Window w;
TwmWindow *tmp_win;
{
int lastx, lasty, width, height, bw2;
int namelen;
int stat;
XEvent event;
Window junk;
namelen = strlen (tmp_win->name);
bw2 = tmp_win->frame_bw * 2;
AddingW = tmp_win->attr.width + bw2;
AddingH = tmp_win->attr.height + tmp_win->title_height + bw2;
width = (SIZE_HINDENT + XTextWidth (Scr->SizeFont.font,
tmp_win->name, namelen));
height = Scr->SizeFont.height + SIZE_VINDENT * 2;
XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY,
(unsigned int *)&DragWidth, (unsigned int *)&DragHeight,
&JunkBW, &JunkDepth);
XWarpPointer(dpy, None, w,
0, 0, 0, 0, DragWidth/2, DragHeight/2);
XQueryPointer (dpy, Scr->Root, &JunkRoot,
&JunkChild, &JunkX, &JunkY,
&AddingX, &AddingY, &JunkMask);
/*****
Scr->SizeStringOffset = width +
XTextWidth(Scr->SizeFont.font, ": ", 2);
XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset +
Scr->SizeStringWidth, height);
XDrawImageString (dpy, Scr->SizeWindow, Scr->NormalGC, width,
SIZE_VINDENT + Scr->SizeFont.font->ascent,
": ", 2);
*****/
lastx = -10000;
lasty = -10000;
/*****
MoveOutline(Scr->Root,
origDragX - JunkBW, origDragY - JunkBW,
DragWidth * JunkBW, DragHeight * JunkBW,
tmp_win->frame_bw,
tmp_win->title_height);
*****/
MenuStartResize(tmp_win, origDragX, origDragY, DragWidth, DragHeight);
while (TRUE)
{
XMaskEvent(dpy,
ButtonPressMask | PointerMotionMask, &event);
if (event.type == MotionNotify) {
/* discard any extra motion events before a release */
while(XCheckMaskEvent(dpy,
ButtonMotionMask | ButtonPressMask, &event))
if (event.type == ButtonPress)
break;
}
if (event.type == ButtonPress)
{
MenuEndResize(tmp_win);
XMoveResizeWindow(dpy, w, AddingX, AddingY, AddingW, AddingH);
break;
}
/* if (!DispatchEvent ()) continue; */
if (event.type != MotionNotify) {
continue;
}
/*
* XXX - if we are going to do a loop, we ought to consider
* using multiple GXxor lines so that we don't need to
* grab the server.
*/
XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
&JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
if (lastx != AddingX || lasty != AddingY)
{
MenuDoResize(AddingX, AddingY, tmp_win);
lastx = AddingX;
lasty = AddingY;
}
}
}
/***********************************************************************
*
* Procedure:
* ExecuteFunction - execute a twm root function
*
* Inputs:
* func - the function to execute
* action - the menu action to execute
* w - the window to execute this function on
* tmp_win - the twm window structure
* event - the event that caused the function
* context - the context in which the button was pressed
* pulldown- flag indicating execution from pull down menu
*
* Returns:
* TRUE if should continue with remaining actions else FALSE to abort
*
***********************************************************************
*/
int
ExecuteFunction(func, action, w, tmp_win, eventp, context, pulldown)
int func;
char *action;
Window w;
TwmWindow *tmp_win;
XEvent *eventp;
int context;
int pulldown;
{
static Time last_time = 0;
char tmp[200];
char *ptr;
char buff[MAX_FILE_SIZE];
int count, fd;
Window rootw;
int origX, origY;
int do_next_action = TRUE;
int moving_icon = FALSE;
Bool fromtitlebar = False;
extern int ConstrainedMoveTime;
RootFunction = NULL;
if (Cancel)
return TRUE; /* XXX should this be FALSE? */
switch (func)
{
case F_UPICONMGR:
case F_LEFTICONMGR:
case F_RIGHTICONMGR:
case F_DOWNICONMGR:
case F_FORWICONMGR:
case F_BACKICONMGR:
case F_NEXTICONMGR:
case F_PREVICONMGR:
case F_NOP:
case F_TITLE:
case F_DELTASTOP:
case F_RAISELOWER:
case F_WARPTOSCREEN:
case F_WARPTO:
case F_WARPRING:
case F_WARPTOICONMGR:
case F_COLORMAP:
break;
default:
XGrabPointer(dpy, Scr->Root, True,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
Scr->Root, Scr->WaitCursor, CurrentTime);
break;
}
switch (func)
{
case F_NOP:
case F_TITLE:
break;
case F_DELTASTOP:
if (WindowMoved) do_next_action = FALSE;
break;
case F_RESTART:
XSync (dpy, 0);
Reborder (eventp->xbutton.time);
XSync (dpy, 0);
execvp(*Argv, Argv);
fprintf (stderr, "%s: unable to restart: %s\n", ProgramName, *Argv);
break;
case F_UPICONMGR:
case F_DOWNICONMGR:
case F_LEFTICONMGR:
case F_RIGHTICONMGR:
case F_FORWICONMGR:
case F_BACKICONMGR:
MoveIconManager(func);
break;
case F_NEXTICONMGR:
case F_PREVICONMGR:
JumpIconManager(func);
break;
case F_SHOWLIST:
if (Scr->NoIconManagers)
break;
DeIconify(Scr->iconmgr.twm_win);
XRaiseWindow(dpy, Scr->iconmgr.twm_win->frame);
break;
case F_HIDELIST:
if (Scr->NoIconManagers)
break;
HideIconManager ();
break;
case F_SORTICONMGR:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
{
int save_sort;
save_sort = Scr->SortIconMgr;
Scr->SortIconMgr = TRUE;
if (context == C_ICONMGR)
SortIconManager((IconMgr *) NULL);
else if (tmp_win->iconmgr)
SortIconManager(tmp_win->iconmgrp);
else
XBell(dpy, 0);
Scr->SortIconMgr = save_sort;
}
break;
case F_IDENTIFY:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
Identify(tmp_win);
break;
case F_VERSION:
Identify ((TwmWindow *) NULL);
break;
case F_AUTORAISE:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
tmp_win->auto_raise = !tmp_win->auto_raise;
if (tmp_win->auto_raise) ++(Scr->NumAutoRaises);
else --(Scr->NumAutoRaises);
break;
case F_BEEP:
XBell(dpy, 0);
break;
case F_POPUP:
tmp_win = (TwmWindow *)action;
if (Scr->WindowFunction.func != NULL)
{
ExecuteFunction(Scr->WindowFunction.func,
Scr->WindowFunction.item->action,
w, tmp_win, eventp, C_FRAME, FALSE);
}
else
{
DeIconify(tmp_win);
XRaiseWindow (dpy, tmp_win->frame);
}
break;
case F_RESIZE:
EventHandler[EnterNotify] = HandleUnknown;
EventHandler[LeaveNotify] = HandleUnknown;
if (DeferExecution(context, func, Scr->MoveCursor))
return TRUE;
PopDownMenu();
if (pulldown)
XWarpPointer(dpy, None, Scr->Root,
0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root);
if (w != tmp_win->icon_w) { /* can't resize icons */
if ((Context == C_FRAME || Context == C_WINDOW || Context == C_TITLE)
&& fromMenu)
resizeFromCenter(w, tmp_win);
else {
/*
* see if this is being done from the titlebar
*/
fromtitlebar =
belongs_to_twm_window (tmp_win, eventp->xbutton.window);
/* Save pointer position so we can tell if it was moved or
not during the resize. */
ResizeOrigX = eventp->xbutton.x_root;
ResizeOrigY = eventp->xbutton.y_root;
StartResize (eventp, tmp_win, fromtitlebar);
do {
XMaskEvent(dpy,
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
ButtonMotionMask, &Event);
if (fromtitlebar && Event.type == ButtonPress) {
fromtitlebar = False;
continue;
}
if (Event.type == MotionNotify) {
/* discard any extra motion events before a release */
while
(XCheckMaskEvent
(dpy, ButtonMotionMask | ButtonReleaseMask, &Event))
if (Event.type == ButtonRelease)
break;
}
if (!DispatchEvent ()) continue;
} while (!(Event.type == ButtonRelease || Cancel));
return TRUE;
}
}
break;
case F_ZOOM:
case F_HORIZOOM:
case F_FULLZOOM:
case F_LEFTZOOM:
case F_RIGHTZOOM:
case F_TOPZOOM:
case F_BOTTOMZOOM:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
fullzoom(tmp_win, func);
break;
case F_MOVE:
case F_FORCEMOVE:
if (DeferExecution(context, func, Scr->MoveCursor))
return TRUE;
PopDownMenu();
rootw = eventp->xbutton.root;
MoveFunction = func;
if (pulldown)
XWarpPointer(dpy, None, Scr->Root,
0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root);
EventHandler[EnterNotify] = HandleUnknown;
EventHandler[LeaveNotify] = HandleUnknown;
if (!Scr->NoGrabServer || !Scr->OpaqueMove) {
XGrabServer(dpy);
}
XGrabPointer(dpy, eventp->xbutton.root, True,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | PointerMotionMask, /* PointerMotionHintMask */
GrabModeAsync, GrabModeAsync,
Scr->Root, Scr->MoveCursor, CurrentTime);
if (context == C_ICON && tmp_win->icon_w)
{
w = tmp_win->icon_w;
DragX = eventp->xbutton.x;
DragY = eventp->xbutton.y;
moving_icon = TRUE;
}
else if (w != tmp_win->icon_w)
{
XTranslateCoordinates(dpy, w, tmp_win->frame,
eventp->xbutton.x,
eventp->xbutton.y,
&DragX, &DragY, &JunkChild);
w = tmp_win->frame;
}
DragWindow = None;
XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY,
(unsigned int *)&DragWidth, (unsigned int *)&DragHeight, &JunkBW,
&JunkDepth);
origX = eventp->xbutton.x_root;
origY = eventp->xbutton.y_root;
CurrentDragX = origDragX;
CurrentDragY = origDragY;
/*
* only do the constrained move if timer is set; need to check it
* in case of stupid or wicked fast servers
*/
if (ConstrainedMoveTime &&
(eventp->xbutton.time - last_time) < ConstrainedMoveTime)
{
int width, height;
ConstMove = TRUE;
ConstMoveDir = MOVE_NONE;
ConstMoveX = eventp->xbutton.x_root - DragX - JunkBW;
ConstMoveY = eventp->xbutton.y_root - DragY - JunkBW;
width = DragWidth + 2 * JunkBW;
height = DragHeight + 2 * JunkBW;
ConstMoveXL = ConstMoveX + width/3;
ConstMoveXR = ConstMoveX + 2*(width/3);
ConstMoveYT = ConstMoveY + height/3;
ConstMoveYB = ConstMoveY + 2*(height/3);
XWarpPointer(dpy, None, w,
0, 0, 0, 0, DragWidth/2, DragHeight/2);
XQueryPointer(dpy, w, &JunkRoot, &JunkChild,
&JunkX, &JunkY, &DragX, &DragY, &JunkMask);
}
last_time = eventp->xbutton.time;
if (!Scr->OpaqueMove)
{
InstallRootColormap();
if (!Scr->MoveDelta)
{
/*
* Draw initial outline. This was previously done the
* first time though the outer loop by dropping out of
* the XCheckMaskEvent inner loop down to one of the
* MoveOutline's below.
*/
MoveOutline(rootw,
origDragX - JunkBW, origDragY - JunkBW,
DragWidth + 2 * JunkBW, DragHeight + 2 * JunkBW,
tmp_win->frame_bw,
moving_icon ? 0 : tmp_win->title_height);
/*
* This next line causes HandleReleaseNotify to call
* XRaiseWindow(). This is solely to preserve the
* previous behaviour that raises a window being moved
* on button release even if you never actually moved
* any distance (unless you move less than MoveDelta or
* NoRaiseMove is set or OpaqueMove is set).
*/
DragWindow = w;
}
}
/*
* see if this is being done from the titlebar
*/
fromtitlebar = belongs_to_twm_window (tmp_win, eventp->xbutton.window);
if (menuFromFrameOrWindowOrTitlebar) {
/* warp the pointer to the middle of the window */
XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0,
origDragX + DragWidth / 2,
origDragY + DragHeight / 2);
XFlush(dpy);
}
while (TRUE)
{
long releaseEvent = menuFromFrameOrWindowOrTitlebar ?
ButtonPress : ButtonRelease;
long movementMask = menuFromFrameOrWindowOrTitlebar ?
PointerMotionMask : ButtonMotionMask;
/* block until there is an interesting event */
XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
ExposureMask | movementMask |
VisibilityChangeMask, &Event);
/* throw away enter and leave events until release */
if (Event.xany.type == EnterNotify ||
Event.xany.type == LeaveNotify) continue;
if (Event.type == MotionNotify) {
/* discard any extra motion events before a logical release */
while(XCheckMaskEvent(dpy,
movementMask | releaseEvent, &Event))
if (Event.type == releaseEvent)
break;
}
/* test to see if we have a second button press to abort move */
if (!menuFromFrameOrWindowOrTitlebar)
if (Event.type == ButtonPress && DragWindow != None) {
if (Scr->OpaqueMove)
XMoveWindow (dpy, DragWindow, origDragX, origDragY);
else
MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
DragWindow = None;
}
if (fromtitlebar && Event.type == ButtonPress) {
fromtitlebar = False;
CurrentDragX = origX = Event.xbutton.x_root;
CurrentDragY = origY = Event.xbutton.y_root;
XTranslateCoordinates (dpy, rootw, tmp_win->frame,
origX, origY,
&DragX, &DragY, &JunkChild);
continue;
}
if (!DispatchEvent2 ()) continue;
if (Cancel)
{
WindowMoved = FALSE;
if (!Scr->OpaqueMove)
UninstallRootColormap();
return TRUE; /* XXX should this be FALSE? */
}
if (Event.type == releaseEvent)
{
MoveOutline(rootw, 0, 0, 0, 0, 0, 0);
if (moving_icon &&
((CurrentDragX != origDragX ||
CurrentDragY != origDragY)))
tmp_win->icon_moved = TRUE;
if (!Scr->OpaqueMove && menuFromFrameOrWindowOrTitlebar)
XMoveWindow(dpy, DragWindow,
Event.xbutton.x_root - DragWidth / 2,
Event.xbutton.y_root - DragHeight / 2);
break;
}
/* something left to do only if the pointer moved */
if (Event.type != MotionNotify)
continue;
XQueryPointer(dpy, rootw, &(eventp->xmotion.root), &JunkChild,
&(eventp->xmotion.x_root), &(eventp->xmotion.y_root),
&JunkX, &JunkY, &JunkMask);
if (DragWindow == None &&
abs(eventp->xmotion.x_root - origX) < Scr->MoveDelta &&
abs(eventp->xmotion.y_root - origY) < Scr->MoveDelta)
continue;
WindowMoved = TRUE;
DragWindow = w;
if (!Scr->NoRaiseMove && Scr->OpaqueMove) /* can't restore... */
XRaiseWindow(dpy, DragWindow);
if (ConstMove)
{
switch (ConstMoveDir)
{
case MOVE_NONE:
if (eventp->xmotion.x_root < ConstMoveXL ||
eventp->xmotion.x_root > ConstMoveXR)
ConstMoveDir = MOVE_HORIZ;
if (eventp->xmotion.y_root < ConstMoveYT ||
eventp->xmotion.y_root > ConstMoveYB)
ConstMoveDir = MOVE_VERT;
XQueryPointer(dpy, DragWindow, &JunkRoot, &JunkChild,
&JunkX, &JunkY, &DragX, &DragY, &JunkMask);
break;
case MOVE_VERT:
ConstMoveY = eventp->xmotion.y_root - DragY - JunkBW;
break;
case MOVE_HORIZ:
ConstMoveX= eventp->xmotion.x_root - DragX - JunkBW;
break;
}
if (ConstMoveDir != MOVE_NONE)
{
int xl, yt, xr, yb, w, h;
xl = ConstMoveX;
yt = ConstMoveY;
w = DragWidth + 2 * JunkBW;
h = DragHeight + 2 * JunkBW;
if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
{
xr = xl + w;
yb = yt + h;
if (xl < 0)
xl = 0;
if (xr > Scr->MyDisplayWidth)
xl = Scr->MyDisplayWidth - w;
if (yt < 0)
yt = 0;
if (yb > Scr->MyDisplayHeight)
yt = Scr->MyDisplayHeight - h;
}
CurrentDragX = xl;
CurrentDragY = yt;
if (Scr->OpaqueMove)
XMoveWindow(dpy, DragWindow, xl, yt);
else
MoveOutline(eventp->xmotion.root, xl, yt, w, h,
tmp_win->frame_bw,
moving_icon ? 0 : tmp_win->title_height);
}
}
else if (DragWindow != None)
{
int xl, yt, xr, yb, w, h;
if (!menuFromFrameOrWindowOrTitlebar) {
xl = eventp->xmotion.x_root - DragX - JunkBW;
yt = eventp->xmotion.y_root - DragY - JunkBW;
}
else {
xl = eventp->xmotion.x_root - (DragWidth / 2);
yt = eventp->xmotion.y_root - (DragHeight / 2);
}
w = DragWidth + 2 * JunkBW;
h = DragHeight + 2 * JunkBW;
if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
{
xr = xl + w;
yb = yt + h;
if (xl < 0)
xl = 0;
if (xr > Scr->MyDisplayWidth)
xl = Scr->MyDisplayWidth - w;
if (yt < 0)
yt = 0;
if (yb > Scr->MyDisplayHeight)
yt = Scr->MyDisplayHeight - h;
}
CurrentDragX = xl;
CurrentDragY = yt;
if (Scr->OpaqueMove)
XMoveWindow(dpy, DragWindow, xl, yt);
else
MoveOutline(eventp->xmotion.root, xl, yt, w, h,
tmp_win->frame_bw,
moving_icon ? 0 : tmp_win->title_height);
}
}
if (!Scr->OpaqueMove && DragWindow == None)
UninstallRootColormap();
break;
case F_FUNCTION:
{
MenuRoot *mroot;
MenuItem *mitem;
if ((mroot = FindMenuRoot(action)) == NULL)
{
fprintf (stderr, "%s: couldn't find function \"%s\"\n",
ProgramName, action);
return TRUE;
}
if (NeedToDefer(mroot) && DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
else
{
for (mitem = mroot->first; mitem != NULL; mitem = mitem->next)
{
if (!ExecuteFunction (mitem->func, mitem->action, w,
tmp_win, eventp, context, pulldown))
break;
}
}
}
break;
case F_DEICONIFY:
case F_ICONIFY:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (tmp_win->icon)
{
DeIconify(tmp_win);
}
else if (func == F_ICONIFY)
{
Iconify (tmp_win, eventp->xbutton.x_root - 5,
eventp->xbutton.y_root - 5);
}
break;
case F_RAISELOWER:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (!WindowMoved) {
XWindowChanges xwc;
xwc.stack_mode = Opposite;
if (w != tmp_win->icon_w)
w = tmp_win->frame;
XConfigureWindow (dpy, w, CWStackMode, &xwc);
}
break;
case F_RAISE:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
/* check to make sure raise is not from the WindowFunction */
if (w == tmp_win->icon_w && Context != C_ROOT)
XRaiseWindow(dpy, tmp_win->icon_w);
else
XRaiseWindow(dpy, tmp_win->frame);
break;
case F_LOWER:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (w == tmp_win->icon_w)
XLowerWindow(dpy, tmp_win->icon_w);
else
XLowerWindow(dpy, tmp_win->frame);
break;
case F_FOCUS:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (tmp_win->icon == FALSE)
{
if (!Scr->FocusRoot && Scr->Focus == tmp_win)
{
FocusOnRoot();
}
else
{
if (Scr->Focus != NULL) {
SetBorder (Scr->Focus, False);
if (Scr->Focus->hilite_w)
XUnmapWindow (dpy, Scr->Focus->hilite_w);
}
InstallWindowColormaps (0, tmp_win);
if (tmp_win->hilite_w) XMapWindow (dpy, tmp_win->hilite_w);
SetBorder (tmp_win, True);
SetFocus (tmp_win, eventp->xbutton.time);
Scr->FocusRoot = FALSE;
Scr->Focus = tmp_win;
}
}
break;
case F_DESTROY:
if (DeferExecution(context, func, Scr->DestroyCursor))
return TRUE;
if (tmp_win->iconmgr)
XBell(dpy, 0);
else
XKillClient(dpy, tmp_win->w);
break;
case F_DELETE:
if (DeferExecution(context, func, Scr->DestroyCursor))
return TRUE;
if (tmp_win->iconmgr) /* don't send ourself a message */
HideIconManager ();
else if (tmp_win->protocols & DoesWmDeleteWindow)
SendDeleteWindowMessage (tmp_win, LastTimestamp());
else
XBell (dpy, 0);
break;
case F_SAVEYOURSELF:
if (DeferExecution (context, func, Scr->SelectCursor))
return TRUE;
if (tmp_win->protocols & DoesWmSaveYourself)
SendSaveYourselfMessage (tmp_win, LastTimestamp());
else
XBell (dpy, 0);
break;
case F_CIRCLEUP:
XCirculateSubwindowsUp(dpy, Scr->Root);
break;
case F_CIRCLEDOWN:
XCirculateSubwindowsDown(dpy, Scr->Root);
break;
case F_EXEC:
PopDownMenu();
if (!Scr->NoGrabServer) {
XUngrabServer (dpy);
XSync (dpy, 0);
}
Execute(action);
break;
case F_UNFOCUS:
FocusOnRoot();
break;
case F_CUT:
strcpy(tmp, action);
strcat(tmp, "\n");
XStoreBytes(dpy, tmp, strlen(tmp));
break;
case F_CUTFILE:
ptr = XFetchBytes(dpy, &count);
if (ptr) {
if (sscanf (ptr, "%s", tmp) == 1) {
XFree (ptr);
ptr = ExpandFilename(tmp);
if (ptr) {
fd = open (ptr, 0);
if (fd >= 0) {
count = read (fd, buff, MAX_FILE_SIZE - 1);
if (count > 0) XStoreBytes (dpy, buff, count);
close(fd);
} else {
fprintf (stderr,
"%s: unable to open cut file \"%s\"\n",
ProgramName, tmp);
}
if (ptr != tmp) free (ptr);
}
} else {
XFree(ptr);
}
} else {
fprintf(stderr, "%s: cut buffer is empty\n", ProgramName);
}
break;
case F_WARPTOSCREEN:
{
if (strcmp (action, WARPSCREEN_NEXT) == 0) {
WarpToScreen (Scr->screen + 1, 1);
} else if (strcmp (action, WARPSCREEN_PREV) == 0) {
WarpToScreen (Scr->screen - 1, -1);
} else if (strcmp (action, WARPSCREEN_BACK) == 0) {
WarpToScreen (PreviousScreen, 0);
} else {
WarpToScreen (atoi (action), 0);
}
}
break;
case F_COLORMAP:
{
if (strcmp (action, COLORMAP_NEXT) == 0) {
BumpWindowColormap (tmp_win, 1);
} else if (strcmp (action, COLORMAP_PREV) == 0) {
BumpWindowColormap (tmp_win, -1);
} else {
BumpWindowColormap (tmp_win, 0);
}
}
break;
case F_WARPTO:
{
register TwmWindow *t;
int len;
len = strlen(action);
for (t = Scr->TwmRoot.next; t != NULL; t = t->next) {
if (!strncmp(action, t->class.res_name, len)) break;
}
if (!t) {
for (t = Scr->TwmRoot.next; t != NULL; t = t->next) {
if (!strncmp(action, t->class.res_name, len)) break;
}
if (!t) {
for (t = Scr->TwmRoot.next; t != NULL; t = t->next) {
if (!strncmp(action, t->class.res_class, len)) break;
}
}
}
if (t) {
if (Scr->WarpUnmapped || t->mapped) {
if (!t->mapped) DeIconify (t);
if (!Scr->NoRaiseWarp) XRaiseWindow (dpy, t->frame);
WarpToWindow (t);
}
} else {
XBell (dpy, 0);
}
}
break;
case F_WARPTOICONMGR:
{
TwmWindow *t;
int len;
Window raisewin = None, iconwin = None;
len = strlen(action);
if (len == 0) {
if (tmp_win && tmp_win->list) {
raisewin = tmp_win->list->iconmgr->twm_win->frame;
iconwin = tmp_win->list->icon;
} else if (Scr->iconmgr.active) {
raisewin = Scr->iconmgr.twm_win->frame;
iconwin = Scr->iconmgr.active->w;
}
} else {
for (t = Scr->TwmRoot.next; t != NULL; t = t->next) {
if (strncmp (action, t->icon_name, len) == 0) {
if (t->list && t->list->iconmgr->twm_win->mapped) {
raisewin = t->list->iconmgr->twm_win->frame;
iconwin = t->list->icon;
break;
}
}
}
}
if (raisewin) {
XRaiseWindow (dpy, raisewin);
XWarpPointer (dpy, None, iconwin, 0,0,0,0, 5, 5);
} else {
XBell (dpy, 0);
}
}
break;
case F_WARPRING:
switch (action[0]) {
case 'n':
WarpAlongRing (&eventp->xbutton, True);
break;
case 'p':
WarpAlongRing (&eventp->xbutton, False);
break;
default:
XBell (dpy, 0);
break;
}
break;
case F_FILE:
action = ExpandFilename(action);
fd = open(action, 0);
if (fd >= 0)
{
count = read(fd, buff, MAX_FILE_SIZE - 1);
if (count > 0)
XStoreBytes(dpy, buff, count);
close(fd);
}
else
{
fprintf (stderr, "%s: unable to open file \"%s\"\n",
ProgramName, action);
}
break;
case F_REFRESH:
{
XSetWindowAttributes attributes;
unsigned long valuemask;
valuemask = (CWBackPixel | CWBackingStore | CWSaveUnder);
attributes.background_pixel = Scr->Black;
attributes.backing_store = NotUseful;
attributes.save_under = False;
w = XCreateWindow (dpy, Scr->Root, 0, 0,
(unsigned int) Scr->MyDisplayWidth,
(unsigned int) Scr->MyDisplayHeight,
(unsigned int) 0,
CopyFromParent, (unsigned int) CopyFromParent,
(Visual *) CopyFromParent, valuemask,
&attributes);
XMapWindow (dpy, w);
XDestroyWindow (dpy, w);
XFlush (dpy);
}
break;
case F_WINREFRESH:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (context == C_ICON && tmp_win->icon_w)
w = XCreateSimpleWindow(dpy, tmp_win->icon_w,
0, 0, 9999, 9999, 0, Scr->Black, Scr->Black);
else
w = XCreateSimpleWindow(dpy, tmp_win->frame,
0, 0, 9999, 9999, 0, Scr->Black, Scr->Black);
XMapWindow(dpy, w);
XDestroyWindow(dpy, w);
XFlush(dpy);
break;
case F_QUIT:
Done();
break;
}
if (ButtonPressed == -1) XUngrabPointer(dpy, CurrentTime);
return do_next_action;
}
/***********************************************************************
*
* Procedure:
* DeferExecution - defer the execution of a function to the
* next button press if the context is C_ROOT
*
* Inputs:
* context - the context in which the mouse button was pressed
* func - the function to defer
* cursor - the cursor to display while waiting
*
***********************************************************************
*/
int
DeferExecution(context, func, cursor)
int context, func;
Cursor cursor;
{
if (context == C_ROOT)
{
LastCursor = cursor;
XGrabPointer(dpy, Scr->Root, True,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
Scr->Root, cursor, CurrentTime);
RootFunction = func;
return (TRUE);
}
return (FALSE);
}
/***********************************************************************
*
* Procedure:
* ReGrab - regrab the pointer with the LastCursor;
*
***********************************************************************
*/
ReGrab()
{
XGrabPointer(dpy, Scr->Root, True,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
Scr->Root, LastCursor, CurrentTime);
}
/***********************************************************************
*
* Procedure:
* NeedToDefer - checks each function in the list to see if it
* is one that needs to be defered.
*
* Inputs:
* root - the menu root to check
*
***********************************************************************
*/
NeedToDefer(root)
MenuRoot *root;
{
MenuItem *mitem;
for (mitem = root->first; mitem != NULL; mitem = mitem->next)
{
switch (mitem->func)
{
case F_IDENTIFY:
case F_RESIZE:
case F_MOVE:
case F_FORCEMOVE:
case F_DEICONIFY:
case F_ICONIFY:
case F_RAISELOWER:
case F_RAISE:
case F_LOWER:
case F_FOCUS:
case F_DESTROY:
case F_WINREFRESH:
case F_ZOOM:
case F_FULLZOOM:
case F_HORIZOOM:
case F_RIGHTZOOM:
case F_LEFTZOOM:
case F_TOPZOOM:
case F_BOTTOMZOOM:
case F_AUTORAISE:
return TRUE;
}
}
return FALSE;
}
/***********************************************************************
*
* Procedure:
* Execute - execute the string by /bin/sh
*
* Inputs:
* s - the string containing the command
*
***********************************************************************
*/
void
Execute(s)
char *s;
{
static char buf[256];
char *ds = DisplayString (dpy);
char *colon, *dot1;
char oldDisplay[256];
char *doisplay;
int restorevar = 0;
oldDisplay[0] = '\0';
doisplay=getenv("DISPLAY");
if (doisplay)
strcpy (oldDisplay, doisplay);
/*
* Build a display string using the current screen number, so that
* X programs which get fired up from a menu come up on the screen
* that they were invoked from, unless specifically overridden on
* their command line.
*/
colon = rindex (ds, ':');
if (colon) { /* if host[:]:dpy */
strcpy (buf, "DISPLAY=");
strcat (buf, ds);
colon = buf + 8 + (colon - ds); /* use version in buf */
dot1 = index (colon, '.'); /* first period after colon */
if (!dot1) dot1 = colon + strlen (colon); /* if not there, append */
(void) sprintf (dot1, ".%d", Scr->screen);
putenv (buf);
restorevar = 1;
}
(void) system (s);
if (restorevar) { /* why bother? */
(void) sprintf (buf, "DISPLAY=%s", oldDisplay);
putenv (buf);
}
}
/***********************************************************************
*
* Procedure:
* FocusOnRoot - put input focus on the root window
*
***********************************************************************
*/
void
FocusOnRoot()
{
SetFocus ((TwmWindow *) NULL, LastTimestamp());
if (Scr->Focus != NULL)
{
SetBorder (Scr->Focus, False);
if (Scr->Focus->hilite_w) XUnmapWindow (dpy, Scr->Focus->hilite_w);
}
InstallWindowColormaps(0, &Scr->TwmRoot);
Scr->Focus = NULL;
Scr->FocusRoot = TRUE;
}
DeIconify(tmp_win)
TwmWindow *tmp_win;
{
TwmWindow *t;
/* de-iconify the main window */
if (tmp_win->icon)
{
if (tmp_win->icon_on)
Zoom(tmp_win->icon_w, tmp_win->frame);
else if (tmp_win->group != NULL)
{
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
{
if (tmp_win->group == t->w && t->icon_on)
{
Zoom(t->icon_w, tmp_win->frame);
break;
}
}
}
}
XMapWindow(dpy, tmp_win->w);
tmp_win->mapped = TRUE;
if (Scr->NoRaiseDeicon)
XMapWindow(dpy, tmp_win->frame);
else
XMapRaised(dpy, tmp_win->frame);
SetMapStateProp(tmp_win, NormalState);
if (tmp_win->icon_w) {
XUnmapWindow(dpy, tmp_win->icon_w);
IconDown (tmp_win);
}
if (tmp_win->list)
XUnmapWindow(dpy, tmp_win->list->icon);
if ((Scr->WarpCursor ||
LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)) &&
tmp_win->icon)
WarpToWindow (tmp_win);
tmp_win->icon = FALSE;
tmp_win->icon_on = FALSE;
/* now de-iconify transients */
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
{
if (t->transient && t->transientfor == tmp_win->w)
{
if (t->icon_on)
Zoom(t->icon_w, t->frame);
else
Zoom(tmp_win->icon_w, t->frame);
XMapWindow(dpy, t->w);
t->mapped = TRUE;
if (Scr->NoRaiseDeicon)
XMapWindow(dpy, t->frame);
else
XMapRaised(dpy, t->frame);
SetMapStateProp(t, NormalState);
if (t->icon_w) {
XUnmapWindow(dpy, t->icon_w);
IconDown (t);
}
if (t->list) XUnmapWindow(dpy, t->list->icon);
t->icon = FALSE;
t->icon_on = FALSE;
}
}
XSync (dpy, 0);
}
Iconify(tmp_win, def_x, def_y)
TwmWindow *tmp_win;
int def_x, def_y;
{
TwmWindow *t;
int iconify;
XWindowAttributes winattrs;
unsigned long eventMask;
iconify = ((!tmp_win->iconify_by_unmapping) || tmp_win->transient);
if (iconify)
{
if (tmp_win->icon_w == NULL)
CreateIconWindow(tmp_win, def_x, def_y);
else
IconUp(tmp_win);
XMapRaised(dpy, tmp_win->icon_w);
}
if (tmp_win->list)
XMapWindow(dpy, tmp_win->list->icon);
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
eventMask = winattrs.your_event_mask;
/* iconify transients first */
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
{
if (t->transient && t->transientfor == tmp_win->w)
{
if (iconify)
{
if (t->icon_on)
Zoom(t->icon_w, tmp_win->icon_w);
else
Zoom(t->frame, tmp_win->icon_w);
}
/*
* Prevent the receipt of an UnmapNotify, since that would
* cause a transition to the Withdrawn state.
*/
t->mapped = FALSE;
XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask);
XUnmapWindow(dpy, t->w);
XSelectInput(dpy, t->w, eventMask);
XUnmapWindow(dpy, t->frame);
if (t->icon_w)
XUnmapWindow(dpy, t->icon_w);
SetMapStateProp(t, IconicState);
SetBorder (t, False);
if (t == Scr->Focus)
{
SetFocus ((TwmWindow *) NULL, LastTimestamp());
Scr->Focus = NULL;
Scr->FocusRoot = TRUE;
}
if (t->list) XMapWindow(dpy, t->list->icon);
t->icon = TRUE;
t->icon_on = FALSE;
}
}
if (iconify)
Zoom(tmp_win->frame, tmp_win->icon_w);
/*
* Prevent the receipt of an UnmapNotify, since that would
* cause a transition to the Withdrawn state.
*/
tmp_win->mapped = FALSE;
XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
XUnmapWindow(dpy, tmp_win->w);
XSelectInput(dpy, tmp_win->w, eventMask);
XUnmapWindow(dpy, tmp_win->frame);
SetMapStateProp(tmp_win, IconicState);
SetBorder (tmp_win, False);
if (tmp_win == Scr->Focus)
{
SetFocus ((TwmWindow *) NULL, LastTimestamp());
Scr->Focus = NULL;
Scr->FocusRoot = TRUE;
}
tmp_win->icon = TRUE;
if (iconify)
tmp_win->icon_on = TRUE;
else
tmp_win->icon_on = FALSE;
XSync (dpy, 0);
}
static void Identify (t)
TwmWindow *t;
{
int i, n, twidth, width, height;
int x, y;
unsigned int wwidth, wheight, bw, depth;
Window junk;
int px, py, dummy;
unsigned udummy;
n = 0;
(void) sprintf(Info[n++], "Twm version: %s", Version);
Info[n++][0] = '\0';
if (t) {
XGetGeometry (dpy, t->w, &JunkRoot, &JunkX, &JunkY,
&wwidth, &wheight, &bw, &depth);
(void) XTranslateCoordinates (dpy, t->w, Scr->Root, 0, 0,
&x, &y, &junk);
(void) sprintf(Info[n++], "Name = \"%s\"", t->full_name);
(void) sprintf(Info[n++], "Class.res_name = \"%s\"", t->class.res_name);
(void) sprintf(Info[n++], "Class.res_class = \"%s\"", t->class.res_class);
Info[n++][0] = '\0';
(void) sprintf(Info[n++], "Geometry/root = %dx%d+%d+%d", wwidth, wheight,
x, y);
(void) sprintf(Info[n++], "Border width = %d", bw);
(void) sprintf(Info[n++], "Depth = %d", depth);
}
Info[n++][0] = '\0';
(void) sprintf(Info[n++], "Click to dismiss....");
/* figure out the width and height of the info window */
height = n * (Scr->DefaultFont.height+2);
width = 1;
for (i = 0; i < n; i++)
{
twidth = XTextWidth(Scr->DefaultFont.font, Info[i],
strlen(Info[i]));
if (twidth > width)
width = twidth;
}
if (InfoLines) XUnmapWindow(dpy, Scr->InfoWindow);
width += 10; /* some padding */
if (XQueryPointer (dpy, Scr->Root, &JunkRoot, &JunkChild, &px, &py,
&dummy, &dummy, &udummy)) {
px -= (width / 2);
py -= (height / 3);
if (px + width + BW2 >= Scr->MyDisplayWidth)
px = Scr->MyDisplayWidth - width - BW2;
if (py + height + BW2 >= Scr->MyDisplayHeight)
py = Scr->MyDisplayHeight - height - BW2;
if (px < 0) px = 0;
if (py < 0) py = 0;
} else {
px = py = 0;
}
XMoveResizeWindow(dpy, Scr->InfoWindow, px, py, width, height);
XMapRaised(dpy, Scr->InfoWindow);
InfoLines = n;
}
SetMapStateProp(tmp_win, state)
TwmWindow *tmp_win;
int state;
{
unsigned long data[2]; /* "suggested" by ICCCM version 1 */
data[0] = (unsigned long) state;
data[1] = (unsigned long) (tmp_win->iconify_by_unmapping ? None :
tmp_win->icon_w);
XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32,
PropModeReplace, (unsigned char *) data, 2);
}
Bool GetWMState (w, statep, iwp)
Window w;
int *statep;
Window *iwp;
{
Atom actual_type;
int actual_format;
unsigned long nitems, bytesafter;
unsigned long *datap = NULL;
Bool retval = False;
if (XGetWindowProperty (dpy, w, _XA_WM_STATE, 0L, 2L, False, _XA_WM_STATE,
&actual_type, &actual_format, &nitems, &bytesafter,
(unsigned char **) &datap) != Success || !datap)
return False;
if (nitems <= 2) { /* "suggested" by ICCCM version 1 */
*statep = (int) datap[0];
*iwp = (Window) datap[1];
retval = True;
}
XFree ((char *) datap);
return retval;
}
WarpToScreen (n, inc)
int n, inc;
{
Window dumwin;
int x, y, dumint;
unsigned int dummask;
ScreenInfo *newscr = NULL;
while (!newscr) {
/* wrap around */
if (n < 0)
n = NumScreens - 1;
else if (n >= NumScreens)
n = 0;
newscr = ScreenList[n];
if (!newscr) { /* make sure screen is managed */
if (inc) { /* walk around the list */
n += inc;
continue;
}
fprintf (stderr, "%s: unable to warp to unmanaged screen %d\n",
ProgramName, n);
XBell (dpy, 0);
return;
}
}
if (Scr->screen == n) return; /* already on that screen */
PreviousScreen = Scr->screen;
XQueryPointer (dpy, Scr->Root, &dumwin, &dumwin, &x, &y,
&dumint, &dumint, &dummask);
XWarpPointer (dpy, None, newscr->Root, 0, 0, 0, 0, x, y);
return;
}
/*
* BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS
*/
BumpWindowColormap (tmp, inc)
TwmWindow *tmp;
int inc;
{
int i, j, previously_installed;
ColormapWindow **cwins;
if (!tmp) return;
if (inc && tmp->cmaps.number_cwins > 0) {
cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *)*
tmp->cmaps.number_cwins);
if (cwins) {
if (previously_installed =
/* SUPPRESS 560 */(Scr->cmapInfo.cmaps == &tmp->cmaps &&
tmp->cmaps.number_cwins)) {
for (i = tmp->cmaps.number_cwins; i-- > 0; )
tmp->cmaps.cwins[i]->colormap->state = 0;
}
for (i = 0; i < tmp->cmaps.number_cwins; i++) {
j = i - inc;
if (j >= tmp->cmaps.number_cwins)
j -= tmp->cmaps.number_cwins;
else if (j < 0)
j += tmp->cmaps.number_cwins;
cwins[j] = tmp->cmaps.cwins[i];
}
free((char *) tmp->cmaps.cwins);
tmp->cmaps.cwins = cwins;
if (tmp->cmaps.number_cwins > 1)
bzero (tmp->cmaps.scoreboard,
ColormapsScoreboardLength(&tmp->cmaps));
if (previously_installed)
InstallWindowColormaps(PropertyNotify, (TwmWindow *) NULL);
}
} else
FetchWmColormapWindows (tmp);
}
HideIconManager ()
{
SetMapStateProp (Scr->iconmgr.twm_win, WithdrawnState);
XUnmapWindow(dpy, Scr->iconmgr.twm_win->frame);
if (Scr->iconmgr.twm_win->icon_w)
XUnmapWindow (dpy, Scr->iconmgr.twm_win->icon_w);
Scr->iconmgr.twm_win->mapped = FALSE;
Scr->iconmgr.twm_win->icon = TRUE;
}
SetBorder (tmp, onoroff)
TwmWindow *tmp;
Bool onoroff;
{
if (tmp->highlight) {
if (onoroff) {
XSetWindowBorder (dpy, tmp->frame, tmp->border);
if (tmp->title_w)
XSetWindowBorder (dpy, tmp->title_w, tmp->border);
} else {
XSetWindowBorderPixmap (dpy, tmp->frame, tmp->gray);
if (tmp->title_w)
XSetWindowBorderPixmap (dpy, tmp->title_w, tmp->gray);
}
}
}
DestroyMenu (menu)
MenuRoot *menu;
{
MenuItem *item;
if (menu->w) {
XDeleteContext (dpy, menu->w, MenuContext);
XDeleteContext (dpy, menu->w, ScreenContext);
if (Scr->Shadow) XDestroyWindow (dpy, menu->shadow);
XDestroyWindow(dpy, menu->w);
}
for (item = menu->first; item; ) {
MenuItem *tmp = item;
item = item->next;
free ((char *) tmp);
}
}
/*
* warping routines
*/
void WarpAlongRing (ev, forward)
XButtonEvent *ev;
Bool forward;
{
TwmWindow *r, *head;
if (Scr->RingLeader)
head = Scr->RingLeader;
else if (!(head = Scr->Ring))
return;
if (forward) {
for (r = head->ring.next; r != head; r = r->ring.next) {
if (!r || r->mapped) break;
}
} else {
for (r = head->ring.prev; r != head; r = r->ring.prev) {
if (!r || r->mapped) break;
}
}
if (r && r != head) {
TwmWindow *p = Scr->RingLeader, *t;
Scr->RingLeader = r;
WarpToWindow (r);
if (p && p->mapped &&
XFindContext (dpy, ev->window, TwmContext, (caddr_t *)&t) == XCSUCCESS &&
p == t) {
p->ring.cursor_valid = True;
p->ring.curs_x = ev->x_root - t->frame_x;
p->ring.curs_y = ev->y_root - t->frame_y;
if (p->ring.curs_x < -p->frame_bw ||
p->ring.curs_x >= p->frame_width + p->frame_bw ||
p->ring.curs_y < -p->frame_bw ||
p->ring.curs_y >= p->frame_height + p->frame_bw) {
/* somehow out of window */
p->ring.curs_x = p->frame_width / 2;
p->ring.curs_y = p->frame_height / 2;
}
}
}
}
void WarpToWindow (t)
TwmWindow *t;
{
int x, y;
if (t->auto_raise || !Scr->NoRaiseWarp) AutoRaiseWindow (t);
if (t->ring.cursor_valid) {
x = t->ring.curs_x;
y = t->ring.curs_y;
} else {
x = t->frame_width / 2;
y = t->frame_height / 2;
}
XWarpPointer (dpy, None, t->frame, 0, 0, 0, 0, x, y);
}
/*
* ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all
* client messages will have the following form:
*
* event type ClientMessage
* message type _XA_WM_PROTOCOLS
* window tmp->w
* format 32
* data[0] message atom
* data[1] time stamp
*/
static void send_clientmessage (w, a, timestamp)
Window w;
Atom a;
Time timestamp;
{
XClientMessageEvent ev;
ev.type = ClientMessage;
ev.window = w;
ev.message_type = _XA_WM_PROTOCOLS;
ev.format = 32;
ev.data.l[0] = a;
ev.data.l[1] = timestamp;
XSendEvent (dpy, w, False, 0L, (XEvent *) &ev);
}
SendDeleteWindowMessage (tmp, timestamp)
TwmWindow *tmp;
Time timestamp;
{
send_clientmessage (tmp->w, _XA_WM_DELETE_WINDOW, timestamp);
}
SendSaveYourselfMessage (tmp, timestamp)
TwmWindow *tmp;
Time timestamp;
{
send_clientmessage (tmp->w, _XA_WM_SAVE_YOURSELF, timestamp);
}
SendTakeFocusMessage (tmp, timestamp)
TwmWindow *tmp;
Time timestamp;
{
send_clientmessage (tmp->w, _XA_WM_TAKE_FOCUS, timestamp);
}